package com.ilxqx.framework.generator.core.util;

import com.ilxqx.framework.generator.constant.GenerationConfigConstants;
import com.ilxqx.framework.generator.parser.Table;
import com.ilxqx.framework.util.TemplateUtils;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;

/**
 * 模板生成工具类
 * @author venus
 */
@Slf4j
public final class TemplateGenerationUtils {

	private static final String DELIMITER = "/";
	private static final String JAVA_FILE_SUFFIX = ".java";
	private static final String VUE_FILE_SUFFIX = ".vue";
	private static final String JS_FILE_SUFFIX = ".js";

	/**
	 * 生成Java文件
	 * @param data 数据
	 * @param tableInfo 表信息
	 * @param template 模板信息
	 */
	public static void generateJavaCode(Map<String, Object> data, Table tableInfo, String template, Map<String, String> fileNamePlaceholders) {
		String[] parts = StringUtils.split(template, ":");
		Assert.isTrue(parts.length == 3, "模板名称不能为空");
		String packageName = GenerationConfigConstants.BASE_PACKAGE + (StringUtils.isNotBlank(parts[1]) ? ("." + parts[1]) : "");
		data.put("package", packageName);
		try {
			File file = new File(TemplateGenerationUtils.parseFilePath(packageName));
			if (!file.exists() && !file.mkdirs()) {
				log.warn("目录[{}]无法创建，模板[{}]无法继续生成", file.getAbsolutePath(), parts[0]);
				return;
			}
			TemplateUtils.render(GenerationConfigConstants.BASE_TEMPLATE_PATH + parts[0] + GenerationConfigConstants.TEMPLATE_SUFFIX,
				data, new FileWriter(new File(file, TemplateGenerationUtils.parseFileName(parts[2], tableInfo.getCamelName(), fileNamePlaceholders, TemplateGenerationUtils.JAVA_FILE_SUFFIX))));
			log.info("模板[{}]生成完毕", parts[0]);
		} catch (IOException | TemplateException e) {
			log.warn("模板[{}]生成失败，原因：{}", parts[0], e);
		}
	}

	/**
	 * 解析文件名
	 * @param nameTemplate 文件名模板
	 * @param camelName 大写驼峰表名
	 * @return 文件名
	 */
	private static String parseFileName(String nameTemplate, String camelName, Map<String, String> custom, String suffix) {
		String fileName = StringUtils.replace(nameTemplate, "${userName}", camelName) + suffix;
		for (Map.Entry<String, String> entry : custom.entrySet()) {
			fileName = StringUtils.replace(fileName, "${" + entry.getKey() + "}", entry.getValue());
		}
		return fileName;
	}

	/**
	 * 解析文件存放路径
	 * @param packageName 包名称
	 * @return 路径字符串
	 */
	private static String parseFilePath(String packageName) {
		String packagePath = String.join(DELIMITER, StringUtils.split(packageName, "."));
		return StringUtils.removeEnd(GenerationConfigConstants.ABSOLUTE_CLASS_PATH, DELIMITER) + DELIMITER + packagePath;
	}

	/**
	 * 生成vue或者js代码
	 * @param data 数据
	 * @param tableInfo 表信息
	 * @param template 模板信息
	 * @param fileNamePlaceholders 文件名占位符替换数据
	 * @param isVue 是否生成vue文件
	 */
	public static void generateVueJsCode(Map<String, Object> data, Table tableInfo, String template, Map<String, String> fileNamePlaceholders, boolean isVue) {
		String[] parts = StringUtils.split(template, ":");
		Assert.isTrue(parts.length == 3, "模板名称不能为空");
		String basePath;
		if (isVue) {
			basePath = GenerationConfigConstants.VIEWS_PATH;
		} else {
			basePath = GenerationConfigConstants.SRC_PATH;
		}
		String filePath = basePath + (StringUtils.isNotBlank(parts[1]) ? (StringUtils.replace(parts[1], "${kebabName}", tableInfo.getKebabName())) : "");
		data.put("apiBasePath", StringUtils.replace(parts[1], "${kebabName}", ""));
		try {
			File file = new File(filePath);
			if (!file.exists() && !file.mkdirs()) {
				log.warn("目录[{}]无法创建，模板[{}]无法继续生成", file.getAbsolutePath(), parts[0]);
				return;
			}
			TemplateUtils.render(GenerationConfigConstants.BASE_TEMPLATE_PATH + parts[0] + GenerationConfigConstants.TEMPLATE_SUFFIX,
				data, new FileWriter(new File(file, TemplateGenerationUtils.parseFileName(parts[2], tableInfo.getCamelName(), fileNamePlaceholders, isVue ? TemplateGenerationUtils.VUE_FILE_SUFFIX : TemplateGenerationUtils.JS_FILE_SUFFIX))));
			log.info("模板[{}]生成完毕", parts[0]);
		} catch (IOException | TemplateException e) {
			log.warn("模板[{}]生成失败，原因：{}", parts[0], e);
		}
	}

}
